﻿//程琳 2012-10-27
using System;
using System.Linq;
using System.Collections.Generic;
using System.Web.Security;
using Microhard.Permission.Interface;
using Microhard.Permission.Models;
using System.Configuration;
using Microhard.Permission;
using System.Web.Profile;
using Microhard.Core;
using Microhard.Core.DBUtility;
using Microhard.Core.Algorithm;

namespace Microhard.Permission_MembershipImpl
{
  
    public class UserImpl : IUser
    {
        private IGroup _group = IoC.Resolve<IGroup>();

        #region IUser Members

        public void SignIn(string userName, bool createPersistentCookie)
        {
            FormsAuthentication.SetAuthCookie(userName, createPersistentCookie);
        }

        public void SignOut()
        {
            FormsAuthentication.SignOut();
        }

        public bool ChangePassword(string userName, string oldPassword, string newPassword)
        {
            MembershipUser currentUser = Membership.GetUser(userName);
            return currentUser.ChangePassword(oldPassword, newPassword);
        }

        public ValidationResult MailValidating(User model)
        {
            ValidationResult rtn = new ValidationResult();
            rtn.IsValid = true;
            if (!string.IsNullOrEmpty(model.Email))
            {
                string userName = Membership.GetUserNameByEmail(model.Email);
                if (!string.IsNullOrEmpty(userName))
                {
                    rtn.IsValid = false;
                    rtn.ErrorMsg.Add("Email", "邮件已经被使用");
                }
            }

            return rtn;
        }

        public ValidationResult UserNameValidating(User model)
        {
            ValidationResult rtn = new ValidationResult();
            rtn.IsValid = true;
            if (!string.IsNullOrEmpty(model.UserName))
            {
                MembershipUser currentUser = Membership.GetUser(model.UserName);
                if (currentUser != null)
                {
                    rtn.IsValid = false;
                    rtn.ErrorMsg.Add("UserName", "用户名已经被使用");
                }
            }
            return rtn;
        }

        #endregion

        #region IRepository<User> Members

        public ExecutedResult Add(User model)
        {
            ExecutedResult rtn = new ExecutedResult();
            MicrohardOUGDBDataContext db = new MicrohardOUGDBDataContext();

            if (model == null)
                return rtn;
            try
            {
                MembershipUser newUser = Membership.CreateUser(model.UserName, model.password, model.Email);
                if (newUser != null && model.Roles != null && model.Roles.Count > 0)
                {
                    //添加角色
                    Roles.AddUserToRoles(model.UserName, model.Roles.Select(p => p.RoleName).ToArray());
                    //添加所属组
                    //var gIds = model.BelongedGroups.Select(g => g.ID).ToList();

                    var user = db.aspnet_Users.SingleOrDefault(u => u.UserName == newUser.UserName);
                    //var groupExeResult = _group.AddUserInGroup(user.UserId, gIds);

                    //添加profile信息
                    var pb = ProfileBase.Create(model.UserName);
                    if (!string.IsNullOrEmpty(model.Address))
                    {
                        pb.SetPropertyValue("Address", model.Address);
                    }
                    if (!string.IsNullOrEmpty(model.CellPhone))
                    {
                        pb.SetPropertyValue("CellPhone", model.CellPhone);
                    }
                    if (!string.IsNullOrEmpty(model.Phone))
                    {
                        pb.SetPropertyValue("Phone", model.Phone);
                    }
                    if (!string.IsNullOrEmpty(model.Duty))
                    {
                        pb.SetPropertyValue("Duty", model.Duty);
                    }
                    if (!string.IsNullOrEmpty(model.Department))
                    {
                        pb.SetPropertyValue("Department", model.Department);
                    }
                    if (!string.IsNullOrEmpty(model.Mark))
                    {
                        pb.SetPropertyValue("Mark", model.Mark);
                    }
                    pb.Save();

                }
                rtn.Scope.IsSysManage = true;
            }
            catch (MembershipCreateUserException ex)
            {
                rtn.ErrorMsg.Add("UserAddFailed", "添加用户失败，请联系系统管理员");
                Log.Error("添加用户失败", ex);
            }
            return rtn;
        }


        /// <summary>
        /// Membership使用非hashed算法加密用户密码，会使用用户名作为密钥故，不能修改用户名
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public ExecutedResult Update(User model)
        {
            ExecutedResult rtn = new ExecutedResult();
            if (model == null)
                return rtn;
            //获得user
            var mUser = Membership.GetUser(model.UserName);
            mUser.Email = model.Email;
            //获得角色
            List<Role> deletedRoles = new List<Role>();
            List<Role> addRoles = new List<Role>();
            MicrohardOUGDBDataContext db = new MicrohardOUGDBDataContext();
            var existRoles = db.aspnet_UsersInRoles.Where(r => r.UserId == model.ID).Select(r => new Role
            {
                RoleId = r.RoleId,
                RoleName = r.aspnet_Role.RoleName
            }).ToList();
            var newRoles = model.Roles;
            //对比，获得哪些role需要增加，哪些需要删除
            AlgCompare.DataCompareForCreateAndDelete<Role>(existRoles, newRoles, new RoleCompare(), out deletedRoles, out addRoles);
            
            //获得组
            //List<Group> deleteGroups = new List<Group>();
            //List<Group> addGroups = new List<Group>();
            //var existGroups = db.MicroHard_EntitiesInGroups
            //    .Where(g => g.EntityID == model.ID && g.EntityType == (int)OwnerIDType.User)
            //    .Select(g => g.MicroHard_Group.ToModel()).ToList();
            //var newGroups = model.BelongedGroups;
            //AlgCompare.DataCompareForCreateAndDelete<Group>(existGroups, newGroups, new GroupCompare(), out deleteGroups, out addGroups);
            try
            {
                //更新用户信息
                Membership.UpdateUser(mUser);
                //添加角色信息
                if (addRoles.Count > 0)
                {
                    Roles.AddUserToRoles(model.UserName, addRoles.Select(a => a.RoleName).ToArray());
                }
                //删除角色
                if (deletedRoles.Count > 0)
                {
                    Roles.RemoveUserFromRoles(model.UserName, deletedRoles.Select(a => a.RoleName).ToArray());
                }
                //修改profile
                var pb = ProfileBase.Create(model.UserName);
                pb.SetPropertyValue("Address", model.Address);
                pb.SetPropertyValue("CellPhone", model.CellPhone);
                pb.SetPropertyValue("Phone", model.Phone);
                pb.SetPropertyValue("Duty", model.Duty);
                pb.SetPropertyValue("Department", model.Department);
                pb.SetPropertyValue("Mark", model.Mark);
                pb.Save();
                //删除组
                //var ext = _group.DeleteUserInGroup(model.ID, deleteGroups.Select(g => g.ID).ToList());
                ////添加组
                //var ext2 = _group.AddUserInGroup(model.ID, addGroups.Select(g => g.ID).ToList());
                //if (ext.IsSucceed && ext2.IsSucceed)
                //{
                //    rtn.IsSucceed = true;
                //}
            }
            catch (Exception ex)
            {
                rtn.ErrorMsg.Add("UserUpdateFailed", "修改用户失败，请联系系统管理员");
                Log.Error("修改用户失败", ex);
            }
            return rtn;
        }

        public ExecutedResult Delete(List<Guid> ids)
        {
            ExecutedResult rtn = new ExecutedResult();
            if (ids == null || ids.Count == 0)
            {
                rtn.ErrorMsg.Add("UserDeleteFailed", "删除用户失败，用户未选择");
                return rtn;
            }
            //删除用户所属组
            MicrohardOUGDBDataContext db = new MicrohardOUGDBDataContext();
            var deleteUsers = (from id in ids
                               from user in db.aspnet_Users
                               where user.UserId == id
                               select user).ToList();


            foreach (var u in deleteUsers)
            {
                //是否为admin
                var canDelAdmin = bool.Parse(ConfigurationManager.AppSettings["CanDelAdmin"]);
                if (!canDelAdmin)
                {
                    if (u.LoweredUserName == "admin")
                    {
                        rtn.ErrorMsg.Add("UserDeleteFailed", "Admin属于系统内置账户，无法删除");
                        continue;
                    }
                }
                try
                {
                    //从组中删除
                    var toDelGroups = db.MicroHard_EntitiesInGroups.Where(e => e.EntityID == u.UserId && e.EntityType == (int)OwnerIDType.User);
                    db.MicroHard_EntitiesInGroups.DeleteAllOnSubmit(toDelGroups);
                    //从权限中删除
                    var todelPermis = db.MicroHard_Permissions.Where(p => p.OwnerID == u.UserId && p.OwnerType == (int)OwnerIDType.User);
                    db.MicroHard_Permissions.DeleteAllOnSubmit(todelPermis);
                    //删除用户
                    if (!Membership.DeleteUser(u.UserName))
                    {
                        rtn.ErrorMsg.Add("UserDeleteFailed", "删除用户失败，用户姓名:" + u.UserName);
                    }
                }
                catch (Exception ex)
                {
                    rtn.ErrorMsg.Add("UserDeleteFailed", "删除用户失败，用户姓名:" + u.UserName);
                    Log.Error("删除用户失败", ex);
                    continue;
                }
            }
            return rtn;
        }

        public User GetModelByID(Guid id)
        {
            MicrohardOUGDBDataContext db = new MicrohardOUGDBDataContext();
            var dbUser = db.aspnet_Users.SingleOrDefault(u => u.UserId == id);
            if (dbUser != null)
            {
                var user = dbUser.ToModel();
                user.BelongedGroups = db.MicroHard_EntitiesInGroups.Where(u => u.EntityID == user.ID).Select(g => g.MicroHard_Group.ToModel()).ToList();
                var pb = ProfileBase.Create(dbUser.UserName);
                if (pb.GetPropertyValue("Address") != null)
                {
                    user.Address = pb.GetPropertyValue("Address").ToString();
                }
                if (pb.GetPropertyValue("CellPhone") != null)
                {
                    user.CellPhone = pb.GetPropertyValue("CellPhone").ToString();
                }
                if (pb.GetPropertyValue("Phone") != null)
                {
                    user.Phone = pb.GetPropertyValue("Phone").ToString();
                }
                if (pb.GetPropertyValue("Duty") != null)
                {
                    user.Duty = pb.GetPropertyValue("Duty").ToString();
                }
                if (pb.GetPropertyValue("Department") != null)
                {
                    user.Department = pb.GetPropertyValue("Department").ToString();
                }
                if (pb.GetPropertyValue("Mark") != null)
                {
                    user.Mark = pb.GetPropertyValue("Mark").ToString();
                }
                return user;
            }
            return null;
        }

        public List<User> Query(User Model, int pageIndex, int pageSize, out int totalCount)
        {
            MicrohardOUGDBDataContext db = new MicrohardOUGDBDataContext();
            IEnumerable<aspnet_User> entities = null;
            if (Model != null && !string.IsNullOrEmpty(Model.UserName))
            {
                entities = from b in db.aspnet_Users
                           where b.UserName.Contains(Model.UserName)
                           select b;
            }
            else
            {
                entities = from b in db.aspnet_Users
                           select b;
            }

            totalCount = entities.Count();
            var pagedEntities = entities.OrderByDescending(p => p.UserName).Skip((pageIndex - 1) * pageSize).Take(pageSize).ToList();
            return pagedEntities.Select(p => p.ToModel()).ToList();
        }

        public List<User> Query(User Model)
        {
            MicrohardOUGDBDataContext db = new MicrohardOUGDBDataContext();
            var roles = (from r in db.aspnet_Users
                         select r).OrderBy(r => r.UserName).ToList();
            return roles.Select(x => x.ToModel()).ToList();
        }


        public ExecutedResult Delete(User models)
        {
            throw new NotImplementedException();
        }
        #endregion




        #region IRepository<User> Members


        public User GetModelByModel(User model)
        {
            throw new NotImplementedException();
        }

        #endregion

        #region IUser Members


        public bool ValidatUser(string userName, string pwd)
        {
            return Membership.ValidateUser(userName, pwd);
        }

        #endregion

        #region IUser Members


        public bool IsAdmin(string userName)
        {
            if (!string.IsNullOrEmpty(userName))
            {
                if (userName.ToLower() == "admin")
                    return true;
            }
            return false;
        }

        #endregion

        #region IRepository<User> Members


        public ScopeResult scope
        {
            set;
            get;
        }

        #endregion

        #region IUser Members


        public User GetUserByName(string userName)
        {
            MicrohardOUGDBDataContext db = new MicrohardOUGDBDataContext();
            var dbUser = db.aspnet_Users.SingleOrDefault(u => u.LoweredUserName == userName.ToLower());
            if (dbUser != null)
            {
                var user = dbUser.ToModel();
                user.BelongedGroups = db.MicroHard_EntitiesInGroups.Where(u => u.EntityID == user.ID).Select(g => g.MicroHard_Group.ToModel()).ToList();
                var pb = ProfileBase.Create(dbUser.UserName);
                if (pb.GetPropertyValue("Address") != null)
                {
                    user.Address = pb.GetPropertyValue("Address").ToString();
                }
                if (pb.GetPropertyValue("CellPhone") != null)
                {
                    user.CellPhone = pb.GetPropertyValue("CellPhone").ToString();
                }
                if (pb.GetPropertyValue("Phone") != null)
                {
                    user.Phone = pb.GetPropertyValue("Phone").ToString();
                }
                if (pb.GetPropertyValue("Duty") != null)
                {
                    user.Duty = pb.GetPropertyValue("Duty").ToString();
                }
                if (pb.GetPropertyValue("Department") != null)
                {
                    user.Department = pb.GetPropertyValue("Department").ToString();
                }
                if (pb.GetPropertyValue("Mark") != null)
                {
                    user.Mark = pb.GetPropertyValue("Mark").ToString();
                }
                return user;
            }
            return null;
        }

        #endregion
    }
}
